package net.orange.console.schedule;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.TimerTask;

import net.orange.architecture.audit.IAuditInfo;
import net.orange.architecture.audit.IAuditable;
import net.orange.architecture.audit.IAuditor;
import net.orange.architecture.audit.JobFileAuditor;
import net.orange.architecture.audit.JobInfo;
import net.orange.architecture.process.ProcessFactory;
import net.orange.framework.logic.IJobProcess;
import net.orange.framework.model.Job;

/**
 * System schedule job delegate agent, which extend from the TimerTask object.
 * It is running thread object for the system timer task.
 */
public class JobAgent extends TimerTask implements IAuditable {

	/**
	 * The job object which be delegated, it include the task program & time
	 * period setting.
	 */
	private Job job;

	/**
	 * The auditors which write the task running status.
	 */
	protected static Collection<IAuditor> auditors = new ArrayList<IAuditor>();

	/**
	 * The file auditors which write the task running status.
	 */
	protected static IAuditor auditor = new JobFileAuditor();

	static {
		auditors.add(auditor);
	}

	/**
	 * Constrctuor with the job.
	 * 
	 * @param job
	 *            The job
	 */
	public JobAgent(Job job) {
		this.job = job;
	}

	/**
	 * @return Returns the job.
	 */
	public Job getJob() {
		return job;
	}

	/**
	 * @param job
	 *            The job to set.
	 */
	public void setJob(Job job) {
		this.job = job;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		try {
			notifyAuditor(new JobInfo(
					job.getCode() + "(" + job.getName() + ")",
					JobRuntimeStatus.start, null));

			job.execute();
			job.setLastrun(new Date(System.currentTimeMillis()));
			job.setRuntimes(job.getRuntimes() + 1);

			IJobProcess process = (IJobProcess) ProcessFactory.load(Job.class);
			process.update(job);

			notifyAuditor(new JobInfo(
					job.getCode() + "(" + job.getName() + ")",
					JobRuntimeStatus.end, null));
		} catch (Exception e) {
			notifyAuditor(new JobInfo(
					job.getCode() + "(" + job.getName() + ")",
					JobRuntimeStatus.failed, e.getMessage()));
			e.printStackTrace();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.audit.IAuditable#addAuditor(net.orange.architecture.audit.IAuditor)
	 */
	public void addAuditor(IAuditor auditor) {
		auditors.add(auditor);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.audit.IAuditable#removeAuditor(net.orange.architecture.audit.IAuditor)
	 */
	public void removeAuditor(IAuditor auditor) {
		if (auditors != null)
			auditors.remove(auditor);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.audit.IAuditable#notifyAuditor(net.orange.architecture.audit.IAuditInfo)
	 */
	public void notifyAuditor(IAuditInfo info) {
		if (auditors != null)
			for (IAuditor auditor : auditors)
				if (auditor != null)
					auditor.update(info);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.console.job.Job#getCode()
	 */
	public String getCode() {
		return job.getCode();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.console.job.Job#getDescription()
	 */
	public String getDescription() {
		return job.getDescription();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.console.job.Job#getInterval_hour()
	 */
	public long getInterval_hour() {
		return job.getInterval_hour();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.console.job.Job#getInterval_second()
	 */
	public long getInterval_second() {
		return job.getInterval_second();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.console.job.Job#getName()
	 */
	public String getName() {
		return job.getName();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.vo.BaseValueObject#getPk()
	 */
	public long getPk() {
		return job.getPk();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.console.job.Job#getProgram()
	 */
	public String getProgram() {
		return job.getProgram();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.console.job.Job#getStartdate()
	 */
	public Date getStartdate() {
		return job.getStarttime();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.console.job.Job#getStatus()
	 */
	public String getStatus() {
		return job.getStatus();
	}
}